﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace Barebones.Communication
{
    public class Forum
    {
        interface ICallback
        {
            void Fire(Object param);
            bool IsForInstance(Object instance);
        }

        class Callback<T> : ICallback where T : class //only support class to prevent boxing issues
        {
            Action<T> m_Callback;

            public Callback(Action<T> callback)
            {
                m_Callback = callback;
            }

            public bool IsForInstance(Object instance)
            {
                return m_Callback.Target == instance;
            }

            public void Fire(Object item)
            {
                Debug.Assert(item.GetType() == typeof(T));
                m_Callback( (T)item );
            }
        }

        Dictionary<Type, List<ICallback>> m_Callbacks = new Dictionary<Type, List<ICallback>>();

        public void RegisterListener<T>(Action<T> callback) where T : class
        {
            if (!m_Callbacks.ContainsKey(typeof(T)))
                m_Callbacks.Add(typeof(T), new List<ICallback>());

            m_Callbacks[typeof(T)].Add(new Callback<T>(callback));
        }

        public void UnRegisterListener<T>(Object instance) where T : class
        {
            List<ICallback> typecallbacks = m_Callbacks[typeof(T)];

            for(int i = typecallbacks.Count - 1; i >= 0; --i)
            {
                if (typecallbacks[i].IsForInstance(instance))
                    typecallbacks.RemoveAt(i);
            }
        }

        public void Fire<T>(T message) where T : class
        {
            List<ICallback> tonotify;
            if (!m_Callbacks.TryGetValue(typeof(T), out tonotify))
                return;

            tonotify.ForEach( item => item.Fire(message) );
        }
    }
}
